{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Gradient Matching Attack on a Pytorch Classifier"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook, we will learn how to use ART to run a clean-label gradient matching poisoning attack on a neural network trained with Pytorch. We will be training our data on a subset of the CIFAR-10 dataset. The methods described are derived from [this paper](https://arxiv.org/abs/2009.02276) by Geiping, et. al. 2020."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train a model to attack\n",
    "\n",
    "In this example, we use a RESNET50 model on the CIFAR dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "0it [00:00, ?it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Final test accuracy: 9.908000\n",
      "Model and data preparation done.\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import os, sys\n",
    "import tqdm\n",
    "from tqdm import trange\n",
    "\n",
    "module_path = os.path.abspath(os.path.join('..'))\n",
    "if module_path not in sys.path:\n",
    "    sys.path.append(module_path)\n",
    "module_path = os.path.abspath(os.path.join('.'))\n",
    "if module_path not in sys.path:\n",
    "    sys.path.append(module_path)\n",
    "\n",
    "from art.estimators.classification import PyTorchClassifier\n",
    "from art.utils import load_cifar10\n",
    "\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "from torch.utils.data import TensorDataset, DataLoader\n",
    "\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "\n",
    "(x_train, y_train), (x_test, y_test), min_, max_ = load_cifar10()\n",
    "\n",
    "mean = np.mean(x_train,axis=(0,1,2,3))\n",
    "std = np.std(x_train,axis=(0,1,2,3))\n",
    "x_train = (x_train-mean)/(std+1e-7)\n",
    "x_test = (x_test-mean)/(std+1e-7)\n",
    "\n",
    "x_train = np.transpose(x_train, [0, 3,1,2])\n",
    "x_test = np.transpose(x_test, [0, 3,1,2])\n",
    "\n",
    "min_ = (min_-mean)/(std+1e-7)\n",
    "max_ = (max_-mean)/(std+1e-7)\n",
    "\n",
    "\n",
    "# Model from: https://github.com/kuangliu/pytorch-cifar\n",
    "# MIT License\n",
    "class BasicBlock(nn.Module):\n",
    "    expansion = 1\n",
    "\n",
    "    def __init__(self, in_planes, planes, stride=1):\n",
    "        super(BasicBlock, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(\n",
    "            in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)\n",
    "        self.bn1 = nn.BatchNorm2d(planes)\n",
    "        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,\n",
    "                               stride=1, padding=1, bias=False)\n",
    "        self.bn2 = nn.BatchNorm2d(planes)\n",
    "\n",
    "        self.shortcut = nn.Sequential()\n",
    "        if stride != 1 or in_planes != self.expansion*planes:\n",
    "            self.shortcut = nn.Sequential(\n",
    "                nn.Conv2d(in_planes, self.expansion*planes,\n",
    "                          kernel_size=1, stride=stride, bias=False),\n",
    "                nn.BatchNorm2d(self.expansion*planes)\n",
    "            )\n",
    "\n",
    "    def forward(self, x):\n",
    "        out = F.relu(self.bn1(self.conv1(x)))\n",
    "        out = self.bn2(self.conv2(out))\n",
    "        out += self.shortcut(x)\n",
    "        out = F.relu(out)\n",
    "        return out\n",
    "\n",
    "\n",
    "class Bottleneck(nn.Module):\n",
    "    expansion = 4\n",
    "\n",
    "    def __init__(self, in_planes, planes, stride=1):\n",
    "        super(Bottleneck, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)\n",
    "        self.bn1 = nn.BatchNorm2d(planes)\n",
    "        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,\n",
    "                               stride=stride, padding=1, bias=False)\n",
    "        self.bn2 = nn.BatchNorm2d(planes)\n",
    "        self.conv3 = nn.Conv2d(planes, self.expansion *\n",
    "                               planes, kernel_size=1, bias=False)\n",
    "        self.bn3 = nn.BatchNorm2d(self.expansion*planes)\n",
    "\n",
    "        self.shortcut = nn.Sequential()\n",
    "        if stride != 1 or in_planes != self.expansion*planes:\n",
    "            self.shortcut = nn.Sequential(\n",
    "                nn.Conv2d(in_planes, self.expansion*planes,\n",
    "                          kernel_size=1, stride=stride, bias=False),\n",
    "                nn.BatchNorm2d(self.expansion*planes)\n",
    "            )\n",
    "\n",
    "    def forward(self, x):\n",
    "        out = F.relu(self.bn1(self.conv1(x)))\n",
    "        out = F.relu(self.bn2(self.conv2(out)))\n",
    "        out = self.bn3(self.conv3(out))\n",
    "        out += self.shortcut(x)\n",
    "        out = F.relu(out)\n",
    "        return out\n",
    "\n",
    "\n",
    "class ResNet(nn.Module):\n",
    "    def __init__(self, block, num_blocks, num_classes=10):\n",
    "        super(ResNet, self).__init__()\n",
    "        self.in_planes = 64\n",
    "\n",
    "        self.conv1 = nn.Conv2d(3, 64, kernel_size=3,\n",
    "                               stride=1, padding=1, bias=False)\n",
    "        self.bn1 = nn.BatchNorm2d(64)\n",
    "        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)\n",
    "        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)\n",
    "        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)\n",
    "        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)\n",
    "        self.linear = nn.Linear(512*block.expansion, num_classes)\n",
    "\n",
    "    def _make_layer(self, block, planes, num_blocks, stride):\n",
    "        strides = [stride] + [1]*(num_blocks-1)\n",
    "        layers = []\n",
    "        for stride in strides:\n",
    "            layers.append(block(self.in_planes, planes, stride))\n",
    "            self.in_planes = planes * block.expansion\n",
    "        return nn.Sequential(*layers)\n",
    "\n",
    "    def forward(self, x):\n",
    "        out = F.relu(self.bn1(self.conv1(x)))\n",
    "        out = self.layer1(out)\n",
    "        out = self.layer2(out)\n",
    "        out = self.layer3(out)\n",
    "        out = self.layer4(out)\n",
    "        out = F.avg_pool2d(out, 4)\n",
    "        out = out.view(out.size(0), -1)\n",
    "        out = self.linear(out)\n",
    "        return out\n",
    "\n",
    "\n",
    "def resnet_18():\n",
    "    return ResNet(BasicBlock, [2, 2, 2, 2])\n",
    "\n",
    "\n",
    "# Function to test the model with the test dataset and print the accuracy for the test images\n",
    "def testAccuracy(model, test_loader, max_steps=10):\n",
    "    model_was_training = model.training\n",
    "    model.eval()\n",
    "    accuracy = 0.0\n",
    "    total = 0.0\n",
    "    \n",
    "    with torch.no_grad():\n",
    "        for data in test_loader:\n",
    "            images, labels = data\n",
    "            # run the model on the test set to predict labels\n",
    "            outputs = model(images)\n",
    "            # the label with the highest energy will be our prediction\n",
    "            _, predicted = torch.max(outputs.data, 1)\n",
    "            total += labels.size(0)\n",
    "            accuracy += (predicted == labels).sum().item()\n",
    "    \n",
    "    # compute the accuracy over all test images\n",
    "    accuracy = (100 * accuracy / total)\n",
    "    if model_was_training:\n",
    "      model.train()\n",
    "    return(accuracy)\n",
    "\n",
    "def create_model(x_train, y_train, x_test=None, y_test=None, num_classes=10, batch_size=128, epochs=25, x_trigger=None, y_trigger=None):\n",
    "    if x_test==None or y_test==None:\n",
    "        x_test = x_train\n",
    "        y_test = y_train\n",
    "    model = resnet_18()\n",
    "\n",
    "    if x_trigger is not None:\n",
    "        assert(x_trigger.shape[0] == 1)\n",
    "        x_trigger = torch.tensor(x_trigger, dtype=torch.float32, device=device)\n",
    "\n",
    "    loss_fn = nn.CrossEntropyLoss()\n",
    "    optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4, nesterov=True)\n",
    "    model.to(device)\n",
    "\n",
    "    y_train = np.argmax(y_train, axis=1)\n",
    "    x_tensor = torch.tensor(x_train, dtype=torch.float32, device=device) # transform to torch tensor\n",
    "    y_tensor = torch.tensor(y_train, dtype=torch.long, device=device)\n",
    "\n",
    "    y_test = np.argmax(y_test, axis=1)\n",
    "    x_tensor_test = torch.tensor(x_test, dtype=torch.float32, device=device) # transform to torch tensor\n",
    "    y_tensor_test = torch.tensor(y_test, dtype=torch.long, device=device)\n",
    "\n",
    "    dataset_train = TensorDataset(x_tensor,y_tensor) # create your datset\n",
    "    dataloader_train = DataLoader(dataset_train, batch_size=batch_size)\n",
    "\n",
    "    dataset_test = TensorDataset(x_tensor_test,y_tensor_test) # create your datset\n",
    "    dataloader_test = DataLoader(dataset_test, batch_size=batch_size)\n",
    "\n",
    "    iter = trange(epochs)\n",
    "    for _ in iter:\n",
    "      running_loss = 0.0\n",
    "      total = 0\n",
    "      accuracy = 0\n",
    "      for _, data in enumerate(dataloader_train, 0):\n",
    "        inputs, labels = data\n",
    "        optimizer.zero_grad()\n",
    "\n",
    "        outputs = model(inputs)\n",
    "        loss = loss_fn(outputs, labels)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        _, predicted = torch.max(outputs.data, 1)\n",
    "        total += labels.size(0)\n",
    "        accuracy += (predicted == labels).sum().item()\n",
    "        running_loss += loss.item()\n",
    "      train_accuracy = (accuracy / total)\n",
    "      if x_trigger is not None:\n",
    "        y_ = model(x_trigger)\n",
    "        y_ = F.softmax(y_, dim=-1)[0]\n",
    "        output_target = y_.detach().cpu().numpy()[y_trigger]\n",
    "        iter.set_postfix({'acc': train_accuracy, 'target': output_target})\n",
    "        tqdm.tqdm.write(str(output_target))\n",
    "      else:\n",
    "        iter.set_postfix({'acc': train_accuracy})\n",
    "    test_accuracy = testAccuracy(model, dataloader_test)\n",
    "    print(\"Final test accuracy: %f\" % test_accuracy)\n",
    "\n",
    "    del x_tensor, y_tensor\n",
    "    del x_tensor_test, y_tensor_test\n",
    "    del dataset_train, dataloader_train\n",
    "    del dataset_test, dataloader_test\n",
    "\n",
    "    return model, loss_fn, optimizer\n",
    "\n",
    "\n",
    "model_path = \"../../models/cifar10-resnet18-pytorch-notebook.pth\"\n",
    "if not os.path.exists(model_path):\n",
    "    model, loss_fn, optimizer = create_model(x_train, y_train, epochs=80)\n",
    "    torch.save(model.state_dict(), model_path)\n",
    "else:\n",
    "    model, loss_fn, optimizer = create_model(x_train, y_train, epochs=0)\n",
    "    model.load_state_dict(torch.load(model_path))\n",
    "\n",
    "model_art = PyTorchClassifier(model, input_shape=x_train.shape[1:], loss=loss_fn, optimizer=optimizer, nb_classes=10)\n",
    "\n",
    "print(\"Model and data preparation done.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Choose Target Image from Test Set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from art.utils import to_categorical\n",
    "\n",
    "# A trigger from class 0 will be classified into class 1.\n",
    "class_source = 0\n",
    "class_target = 1\n",
    "index_target = np.where(y_test.argmax(axis=1)==class_source)[0][5]\n",
    "\n",
    "# Trigger sample\n",
    "x_trigger = x_test[index_target:index_target+1]\n",
    "y_trigger  = to_categorical([class_target], nb_classes=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Poison Training Images to Misclassify the Trigger Image\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a9ba3d706b654d9e9d1347b502e5fe31",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/1 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "cf6bdbb6a5f64eecaa4d791568457afc",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/500 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best B-score: 0.5818748831748962\n"
     ]
    }
   ],
   "source": [
    "from art.attacks.poisoning.gradient_matching_attack import GradientMatchingAttack\n",
    "\n",
    "epsilson = 0.01/(std+1e-7)\n",
    "\n",
    "attack = GradientMatchingAttack(model_art,\n",
    "        percent_poison=0.10,\n",
    "        max_trials=1,\n",
    "        max_epochs=500,\n",
    "        clip_values=(min_,max_),\n",
    "        learning_rate_schedule=(np.array([1e-1, 1e-2, 1e-3, 1e-4, 1e-5]), [250, 350, 400, 430, 460]),\n",
    "        epsilon=epsilson,\n",
    "        verbose=1)\n",
    "\n",
    "x_poison, y_poison = attack.poison(x_trigger, y_trigger, x_train, y_train)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Examples of the trigger, an original sample, and the poisoned sample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "plt.imshow(x_trigger[0].transpose([1,2,0])*(std+1e-7)+mean)\n",
    "plt.title('Trigger image')\n",
    "plt.show()\n",
    "\n",
    "index_poisoned_example = np.where([np.any(p!=o) for (p,o) in zip(x_poison,x_train)])[0]\n",
    "plt.imshow(x_train[index_poisoned_example[0]].transpose([1,2,0])*(std+1e-7)+mean)\n",
    "plt.title('Original image')\n",
    "plt.show()\n",
    "\n",
    "plt.imshow(x_poison[index_poisoned_example[0]].transpose([1,2,0])*(std+1e-7)+mean)\n",
    "plt.title('Poisoned image')\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training with Poison Images"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These attacks allow adversaries who can poison your dataset the ability to mislabel any particular target instance of their choosing without manipulating labels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  1%|▏         | 1/80 [00:14<18:31, 14.07s/it, acc=0.376, target=0.0209]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.020920968\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  2%|▎         | 2/80 [00:28<18:17, 14.07s/it, acc=0.583, target=0.0154]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.015409195\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  4%|▍         | 3/80 [00:42<18:03, 14.07s/it, acc=0.682, target=0.0186]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.018587798\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  5%|▌         | 4/80 [00:56<17:49, 14.07s/it, acc=0.74, target=0.0369]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.03688863\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  6%|▋         | 5/80 [01:10<17:38, 14.12s/it, acc=0.788, target=0.0564]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.056420334\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  8%|▊         | 6/80 [01:24<17:26, 14.14s/it, acc=0.827, target=0.0481]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.048127163\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  9%|▉         | 7/80 [01:38<17:13, 14.16s/it, acc=0.861, target=0.0506]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.050582413\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 10%|█         | 8/80 [01:53<17:00, 14.17s/it, acc=0.879, target=0.059]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.058958918\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 11%|█▏        | 9/80 [02:07<16:46, 14.17s/it, acc=0.892, target=0.0673]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.06726132\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 12%|█▎        | 10/80 [02:21<16:30, 14.15s/it, acc=0.905, target=0.0562]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.056229576\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 14%|█▍        | 11/80 [02:35<16:15, 14.14s/it, acc=0.913, target=0.0715]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.07147843\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 15%|█▌        | 12/80 [02:49<16:01, 14.14s/it, acc=0.923, target=0.0874]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.08737667\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 16%|█▋        | 13/80 [03:03<15:47, 14.14s/it, acc=0.924, target=0.086]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.08596856\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 18%|█▊        | 14/80 [03:17<15:32, 14.13s/it, acc=0.931, target=0.123]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.123355106\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 19%|█▉        | 15/80 [03:31<15:18, 14.13s/it, acc=0.935, target=0.0836]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.08357185\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 20%|██        | 16/80 [03:46<15:04, 14.13s/it, acc=0.934, target=0.0984]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.098448165\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 21%|██▏       | 17/80 [04:00<14:49, 14.13s/it, acc=0.936, target=0.107]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.10721302\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 22%|██▎       | 18/80 [04:14<14:35, 14.12s/it, acc=0.938, target=0.126]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.12556186\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 24%|██▍       | 19/80 [04:28<14:21, 14.12s/it, acc=0.939, target=0.112]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11232751\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 25%|██▌       | 20/80 [04:42<14:07, 14.12s/it, acc=0.941, target=0.0986]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.09856177\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 26%|██▋       | 21/80 [04:56<13:53, 14.12s/it, acc=0.941, target=0.072]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.072005235\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 28%|██▊       | 22/80 [05:10<13:39, 14.13s/it, acc=0.941, target=0.0941]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.09408554\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 29%|██▉       | 23/80 [05:24<13:24, 14.12s/it, acc=0.945, target=0.143]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.14295644\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 30%|███       | 24/80 [05:39<13:11, 14.13s/it, acc=0.942, target=0.0988]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.098763734\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 31%|███▏      | 25/80 [05:53<12:57, 14.14s/it, acc=0.944, target=0.107]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.10666917\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 32%|███▎      | 26/80 [06:07<12:43, 14.14s/it, acc=0.945, target=0.0918]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.09183159\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 34%|███▍      | 27/80 [06:21<12:29, 14.15s/it, acc=0.944, target=0.0902]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.09021515\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 35%|███▌      | 28/80 [06:35<12:15, 14.15s/it, acc=0.946, target=0.11]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11031617\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 36%|███▋      | 29/80 [06:49<12:01, 14.15s/it, acc=0.947, target=0.0759]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.07586657\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 38%|███▊      | 30/80 [07:04<11:47, 14.16s/it, acc=0.946, target=0.152]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.15231666\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 39%|███▉      | 31/80 [07:18<11:33, 14.16s/it, acc=0.948, target=0.0835]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.08345677\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 40%|████      | 32/80 [07:32<11:19, 14.16s/it, acc=0.947, target=0.128]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.12797007\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 41%|████▏     | 33/80 [07:46<11:05, 14.16s/it, acc=0.946, target=0.132]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.13184261\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 42%|████▎     | 34/80 [08:00<10:51, 14.16s/it, acc=0.948, target=0.11]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11028243\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 44%|████▍     | 35/80 [08:14<10:37, 14.16s/it, acc=0.947, target=0.13]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1295244\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 45%|████▌     | 36/80 [08:29<10:23, 14.16s/it, acc=0.948, target=0.172]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.172181\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 46%|████▋     | 37/80 [08:43<10:08, 14.15s/it, acc=0.947, target=0.108]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.108013004\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 48%|████▊     | 38/80 [08:57<09:54, 14.14s/it, acc=0.948, target=0.138]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.13825662\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 49%|████▉     | 39/80 [09:11<09:39, 14.14s/it, acc=0.948, target=0.137]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.13709758\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 50%|█████     | 40/80 [09:25<09:25, 14.14s/it, acc=0.95, target=0.095]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.095026456\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 51%|█████▏    | 41/80 [09:39<09:11, 14.14s/it, acc=0.949, target=0.156]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.15563437\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 52%|█████▎    | 42/80 [09:53<08:56, 14.12s/it, acc=0.948, target=0.113]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11280523\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 54%|█████▍    | 43/80 [10:07<08:41, 14.10s/it, acc=0.952, target=0.118]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.118065126\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 55%|█████▌    | 44/80 [10:21<08:27, 14.09s/it, acc=0.949, target=0.103]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.10319721\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 56%|█████▋    | 45/80 [10:35<08:13, 14.10s/it, acc=0.948, target=0.132]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1319594\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 57%|█████▊    | 46/80 [10:50<07:59, 14.11s/it, acc=0.95, target=0.137]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1367653\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 59%|█████▉    | 47/80 [11:04<07:45, 14.12s/it, acc=0.952, target=0.109]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.10917406\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 60%|██████    | 48/80 [11:18<07:31, 14.12s/it, acc=0.951, target=0.126]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.12584516\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 61%|██████▏   | 49/80 [11:32<07:17, 14.12s/it, acc=0.951, target=0.111]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11106715\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 62%|██████▎   | 50/80 [11:46<07:03, 14.13s/it, acc=0.948, target=0.119]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11948199\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 64%|██████▍   | 51/80 [12:00<06:49, 14.13s/it, acc=0.95, target=0.114]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.114476986\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 65%|██████▌   | 52/80 [12:14<06:35, 14.13s/it, acc=0.951, target=0.159]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.15948537\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 66%|██████▋   | 53/80 [12:28<06:21, 14.11s/it, acc=0.95, target=0.0977]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.097685345\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 68%|██████▊   | 54/80 [12:43<06:07, 14.12s/it, acc=0.952, target=0.161]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.16091889\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 69%|██████▉   | 55/80 [12:57<05:52, 14.12s/it, acc=0.95, target=0.118]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11816824\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 70%|███████   | 56/80 [13:11<05:38, 14.12s/it, acc=0.95, target=0.117]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.117391355\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 71%|███████▏  | 57/80 [13:25<05:24, 14.12s/it, acc=0.95, target=0.12]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.119514264\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 72%|███████▎  | 58/80 [13:39<05:10, 14.12s/it, acc=0.952, target=0.0958]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.095783554\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 74%|███████▍  | 59/80 [13:53<04:56, 14.12s/it, acc=0.955, target=0.119]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11944448\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 75%|███████▌  | 60/80 [14:07<04:42, 14.12s/it, acc=0.95, target=0.189]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.18874319\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 76%|███████▋  | 61/80 [14:21<04:28, 14.12s/it, acc=0.95, target=0.148]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.14826103\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 78%|███████▊  | 62/80 [14:36<04:13, 14.10s/it, acc=0.952, target=0.113]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11327739\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 79%|███████▉  | 63/80 [14:50<03:59, 14.11s/it, acc=0.953, target=0.069]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.06896717\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 80%|████████  | 64/80 [15:04<03:45, 14.11s/it, acc=0.951, target=0.0911]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.09106824\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 81%|████████▏ | 65/80 [15:18<03:31, 14.11s/it, acc=0.951, target=0.122]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1224477\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 82%|████████▎ | 66/80 [15:32<03:17, 14.12s/it, acc=0.951, target=0.141]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1405533\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 84%|████████▍ | 67/80 [15:46<03:03, 14.12s/it, acc=0.953, target=0.13]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.13029188\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 85%|████████▌ | 68/80 [16:00<02:49, 14.12s/it, acc=0.953, target=0.127]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1267492\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 86%|████████▋ | 69/80 [16:14<02:35, 14.10s/it, acc=0.952, target=0.122]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.121668346\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 88%|████████▊ | 70/80 [16:28<02:21, 14.11s/it, acc=0.953, target=0.164]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.16406083\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 89%|████████▉ | 71/80 [16:43<02:06, 14.11s/it, acc=0.954, target=0.15]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.14967178\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 90%|█████████ | 72/80 [16:57<01:52, 14.12s/it, acc=0.956, target=0.121]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.12111224\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 91%|█████████▏| 73/80 [17:11<01:38, 14.12s/it, acc=0.95, target=0.14]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.13993573\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 92%|█████████▎| 74/80 [17:25<01:24, 14.12s/it, acc=0.951, target=0.114]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.11379288\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 94%|█████████▍| 75/80 [17:39<01:10, 14.10s/it, acc=0.954, target=0.112]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.112019755\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 95%|█████████▌| 76/80 [17:53<00:56, 14.11s/it, acc=0.953, target=0.162]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.16198677\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 96%|█████████▋| 77/80 [18:07<00:42, 14.12s/it, acc=0.951, target=0.107]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.10707213\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 98%|█████████▊| 78/80 [18:21<00:28, 14.10s/it, acc=0.955, target=0.14]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.13950746\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 99%|█████████▉| 79/80 [18:35<00:14, 14.11s/it, acc=0.953, target=0.166]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.16608614\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 80/80 [18:50<00:00, 14.13s/it, acc=0.95, target=0.199]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.19921567\n",
      "Final test accuracy: 91.694000\n",
      "y_trigger: [[0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]]\n",
      "y_: [[-0.20934106  0.77485    -0.47768652  0.37470865 -0.41368857  0.153992\n",
      "  -0.27345532  0.3594131  -0.4573476   0.16890174]]\n",
      "Poisoning was successful.\n"
     ]
    }
   ],
   "source": [
    "model_poisoned = create_model(x_poison, y_poison, epochs=80, x_trigger=x_trigger, y_trigger=y_trigger.argmax())\n",
    "y_ = model_poisoned[0](torch.tensor(x_trigger, device=device, dtype=torch.float)).detach().cpu().numpy()\n",
    "\n",
    "print(\"y_trigger:\", y_trigger)\n",
    "print(\"y_:\", y_)\n",
    "\n",
    "if np.argmax(y_trigger) == np.argmax(y_):\n",
    "    print(\"Poisoning was successful.\")\n",
    "else:\n",
    "    print(\"Poisoning failed.\")"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "0efaf3e5c0b4bd1ede177191899ec2ef4ee13bfdededa3ba02bc2fc62340f8fa"
  },
  "kernelspec": {
   "display_name": "Python 3.8.12 64-bit ('art': conda)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
